import ArticleInfo from '@/components/ArticleInfo';
import CollectModal from '@/components/CollectModal';
import Comment from '@/components/Comment';
import type { UserModelState } from '@/models/userModel';
import { getArticleById, praise } from '@/services/articles';
import { debounce } from '@/utils';
import useRequest from '@ahooksjs/use-request';
import { CommentOutlined, HeartFilled, LikeFilled, ShareAltOutlined } from '@ant-design/icons';
import { connect, useModel, useParams } from '@umijs/max';
import { message, Skeleton } from 'antd';
import classnames from 'classnames';
import { MdCatalog, MdPreview } from 'md-editor-rt';
import type { TocItem } from 'md-editor-rt/lib/types/MdCatalog';
import type { MouseEvent } from 'react';
import { useEffect, useRef, useState } from 'react';
import styles from './index.less';

interface PropsType {
  content: string;
  dispatch: any;
}
const scrollElement = document.documentElement;

const Index: React.FC<PropsType> = (props) => {
  const { dispatch } = props;
  const collectModalRef = useRef<{
    setCollectModalOpen: (val: boolean) => void;
  }>();
  const { markDownStore } = useModel('markDown');
  const { initialState: { currentUser: { nickname = '' } = {} } = {} } = useModel('@@initialState');
  const [articledataSource, setArticledataSource] = useState<ARTICLEAPI.ARTICLE>();

  const urlParams = useParams<{ id: string }>();
  const { run: getArticleByIdRun, loading } = useRequest(getArticleById, {
    manual: true,
    onSuccess(data) {
      const { code, data: dataSource, message: errorMessage } = data;
      if (code === 200) {
        setArticledataSource(dataSource);
      } else {
        message.error(errorMessage);
      }
    },
  });
  const praiseHandler = async () => {
    const { code, message: errorMessage } = await praise({
      articleId: urlParams.id || '',
      state: articledataSource?.isLike ? 0 : 1,
    });
    if (code === 200) {
      if (articledataSource?.isLike) {
        message.success('已取消点赞!');
      } else {
        message.success('点赞成功!');
      }
      if (articledataSource) {
        articledataSource.isLike = !articledataSource?.isLike;
        setArticledataSource({ ...articledataSource });
      }
    } else {
      message.error(errorMessage);
    }
  };
  const generateId = (_text: string, _level: number, index: number): string => `heading-${index}`;

  const onHtmlChanged = debounce(() => {
    const { hash } = location;
    if (/^#/.test(hash)) {
      const headingId = decodeURIComponent(hash.replace('#', ''));

      if (headingId) {
        const targetHeadDom = document.getElementById(headingId);

        if (targetHeadDom) {
          const scrollLength = (targetHeadDom as HTMLHeadElement).offsetTop;
          window.scrollTo({
            top: scrollLength,
            behavior: 'smooth',
          });
        }
      }
    }
  });

  const collectHandler = () => {
    if (!nickname) {
      dispatch({ type: 'usermodel/changeIsShowLoginModal', payload: true });
      return true;
    }
    if (collectModalRef.current) {
      collectModalRef.current.setCollectModalOpen(true);
    }
  };

  // 收藏成功更新当前文章收藏状态
  const updateCollectState = () => {
    if (articledataSource) {
      articledataSource.isCollect = !articledataSource?.isCollect;
      setArticledataSource({ ...articledataSource });
    }
  };

  const onClick = (e: MouseEvent, t: TocItem) => {
    history.replaceState({}, '', `${location.pathname}#${t.text}`);
  };

  useEffect(() => {
    if (urlParams.id) {
      getArticleByIdRun(urlParams.id);
    }
  }, []);
  return (
    <div className={styles.mdViewWrapper}>
      <div className={styles.mdEditorWrapper}>
        <Skeleton loading={loading} active className={styles.mySkeleton}>
          <div className={styles.mdEditor}>
            <div className={styles.title}>{articledataSource?.articleTitle}</div>
            <MdPreview
              theme={markDownStore.theme}
              language={markDownStore.lang}
              previewTheme={markDownStore.previewTheme}
              codeTheme={markDownStore.codeTheme}
              editorId="md-editor-preview"
              showCodeRowNumber
              onHtmlChanged={onHtmlChanged}
              modelValue={articledataSource?.articleContent || ''}
            />
          </div>
        </Skeleton>
        <div className={styles.rightWrapper}>
          <ArticleInfo articleAuthorInfo={articledataSource?.user} />
          <div className={styles.mdCatalogWrapper}>
            <Skeleton loading={loading} active className={styles.mySkeleton}>
              <MdCatalog
                style={{ backgroundColor: '#fff' }}
                theme={markDownStore.theme}
                editorId="md-editor-preview"
                scrollElement={scrollElement}
                mdHeadingId={generateId}
                onClick={onClick}
              />
            </Skeleton>
            <div className={styles.shortcut}>
              <HeartFilled
                className={classnames(
                  styles.iconNoActivate,
                  articledataSource?.isCollect ? styles.iconActivate : null,
                )}
                onClick={() => collectHandler()}
              />
              <ShareAltOutlined className={classnames(styles.iconNoActivate)} />
              <CommentOutlined
                className={classnames(styles.iconNoActivate)}
                onClick={() =>
                  (document.documentElement.scrollTop = document.documentElement.scrollHeight)
                }
              />
              <LikeFilled
                onClick={praiseHandler}
                className={classnames(
                  styles.iconNoActivate,
                  articledataSource?.isLike ? styles.iconActivate : null,
                )}
              />
            </div>
          </div>
        </div>
      </div>
      <div className={styles.commentWrapper}>
        <Comment />
      </div>
      <CollectModal
        ref={collectModalRef}
        articleId={urlParams.id}
        backHandler={updateCollectState}
      />
    </div>
  );
};

export default connect(({ usermodel }: { usermodel: UserModelState }) => ({
  usermodel,
}))(Index);
